"""
IoT数据处理器基类

提供所有数据处理器的通用功能和接口定义
"""

import asyncio
import logging
from abc import ABC, abstractmethod
from typing import Any, Dict, Optional
from datetime import datetime

from client.es_client import get_es_client
from client.redis_client import get_redis_client
from dao.es_dao.card_dao import get_card, update_online_status
from model.es.card import ElectronicCardModel


class BaseHandler(ABC):
    """IoT数据处理器基类"""
    
    def __init__(self):
        self.logger = logging.getLogger(self.__class__.__name__)
        self._es_client = None
        self._redis_client = None
    
    async def get_es_client(self):
        """获取Elasticsearch客户端"""
        if not self._es_client:
            self._es_client = await get_es_client()
        return self._es_client
    
    def get_redis_client(self):
        """获取Redis客户端"""
        if not self._redis_client:
            self._redis_client = get_redis_client()
        return self._redis_client
    
    async def get_device_card(self, device_id: str) -> Optional[ElectronicCardModel]:
        """
        获取设备卡片信息
        
        Args:
            device_id: 设备ID
            
        Returns:
            设备卡片信息，如果不存在则返回None
        """
        try:
            card = await get_card(device_id)
            return card
        except Exception as e:
            self.logger.error(f"获取设备卡片信息失败: {device_id}, 错误: {e}")
            return None
    
    async def update_device_online_status(self, timestamp: int, device_id: str) -> None:
        """
        更新设备在线状态
        
        Args:
            timestamp: 时间戳
            device_id: 设备ID
        """
        try:
            card = await self.get_device_card(device_id)
            if card and card.es_id:
                await update_online_status(timestamp, card.es_id)
        except Exception as e:
            self.logger.error(f"更新设备在线状态失败: {device_id}, 错误: {e}")
    
    async def redis_hset_async(self, hash_name: str, key: str, value: Any) -> None:
        """
        异步Redis HSET操作
        
        Args:
            hash_name: 哈希表名
            key: 键
            value: 值
        """
        try:
            redis_client = self.get_redis_client()
            await asyncio.to_thread(redis_client.hset, hash_name, key, value)
        except Exception as e:
            self.logger.error(f"Redis HSET操作失败: {hash_name}:{key}, 错误: {e}")
    
    async def redis_hget_async(self, hash_name: str, key: str) -> Optional[bytes]:
        """
        异步Redis HGET操作
        
        Args:
            hash_name: 哈希表名
            key: 键
            
        Returns:
            值，如果不存在则返回None
        """
        try:
            redis_client = self.get_redis_client()
            return await asyncio.to_thread(redis_client.hget, hash_name, key)
        except Exception as e:
            self.logger.error(f"Redis HGET操作失败: {hash_name}:{key}, 错误: {e}")
            return None
    
    def log_processing_start(self, device_id: str, data_type: str) -> None:
        """记录处理开始日志"""
        self.logger.info(f"开始处理{data_type}数据: 设备ID={device_id}")
    
    def log_processing_end(self, device_id: str, data_type: str, success: bool = True) -> None:
        """记录处理结束日志"""
        status = "成功" if success else "失败"
        self.logger.info(f"{data_type}数据处理{status}: 设备ID={device_id}")
    
    def log_error(self, device_id: str, data_type: str, error: Exception) -> None:
        """记录错误日志"""
        self.logger.error(f"{data_type}数据处理异常: 设备ID={device_id}, 错误: {error}")
    
    @abstractmethod
    async def handle(self, device_id: str, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
        """
        处理设备数据的抽象方法
        
        Args:
            device_id: 设备ID
            data: 设备数据
            
        Returns:
            处理结果，可选
        """
        pass
    
    async def process_with_error_handling(self, device_id: str, data: Dict[str, Any], 
                                        data_type: str) -> Optional[Dict[str, Any]]:
        """
        带错误处理的数据处理包装器
        
        Args:
            device_id: 设备ID
            data: 设备数据
            data_type: 数据类型
            
        Returns:
            处理结果
        """
        self.log_processing_start(device_id, data_type)
        
        try:
            result = await self.handle(device_id, data)
            self.log_processing_end(device_id, data_type, True)
            return result
            
        except Exception as e:
            self.log_error(device_id, data_type, e)
            self.log_processing_end(device_id, data_type, False)
            return None